/*
 * Jabberd2-json-libs-java  
 * Copyright (C) 2010 Antti Leppä / Foyt
 * http://www.foyt.fi
 * 
 * License: 
 * 
 * Licensed under GNU General Public License Version 3 (GPL) 
 * http://www.gnu.org/licenses/gpl.html
 */

package fi.foyt.jabberd2json;

/**
 * Defines a filter
 */
public class Filter {
  
  /**
   * Constructs new filter 
   * 
   * @param type Filter's type
   * @param key Filter's key. Used only when type is PAIR
   * @param value Filter's value. Used only when type is PAIR 
   */
  public Filter(FilterType type, String key, String value) {
    this.type = type;
    this.key = key;
    this.value = value;
  }
  
  /**
   * Constructs new filter 
   * 
   * @param type Filter's type
   */
  public Filter(FilterType type) {
    this.type = type;
  }
  
  /**
   * Returns filter's type
   * 
   * @return Filter's type
   */
  public FilterType getType() {
    return type;
  }
  
  /**
   * Returns sub filter
   *  
   * @return Sub filter
   */
  public Filter getSub() {
    return sub;
  }
  
  /**
   * Sets sub filter
   * 
   * @param sub sub filter
   */
  private void setSub(Filter sub) {
    this.sub = sub;
  }
  
  /**
   * Returns next filter
   * 
   * @return Next filter
   */
  public Filter getNext() {
    return next;
  }
  
  /**
   * Sets next filter
   * 
   * @param next Next filter
   */
  private void setNext(Filter next) {
    this.next = next;
  }
  
  /**
   * Returns filter's key
   * 
   * @return Filter's key
   */
  public String getKey() {
    return key;
  }
  
  /**
   * Returns filter's value
   * 
   * @return Filter's value
   */
  public String getValue() {
    return value;
  }
  
  /**
   * Parses filter from string
   * 
   * @param filterText filter string from jabberd2
   * @return Parsed filter object or null if filterText has been empty or invalid 
   */
  public static Filter parseFromString(String filterText) {
    if (filterText.startsWith("(") && filterText.endsWith(")")) {
      char firstChar = filterText.charAt(1);
      
      if (Character.isLetter(firstChar)) {
        String[] tmp = filterText.substring(1, filterText.length() - 1).split(":", 2);
        if (tmp.length == 2) {
          String key = tmp[0];
          String value = tmp[1];
          
          int eqIndex = key.indexOf('='); 
          if (eqIndex > 0)
            key = key.substring(0, eqIndex);
         
          return new Filter(FilterType.PAIR, key, value);
        }
      } else {
        if (firstChar == '&' || firstChar == '|' || firstChar == '!') {
          FilterType type = null;
          
          switch (firstChar) {
            case '&':
              type = FilterType.AND;
            break;
            case '|':
              type = FilterType.OR;
            break;
            case '!':
              type = FilterType.NOT;
            break;
          }
          
          Filter filter = new Filter(type);
          
          int i = 2;
          while (filterText.charAt(i) == '(') {
            int i2 = i;
            i = filterText.indexOf(')') + 1;
            Filter subFilter = parseFromString(filterText.substring(i, i2));
            filter.setSub(subFilter);
            subFilter.setNext(filter);
          }
        }
      }
    } 
      
    return null;
  }
  
  private FilterType type;
  private String key;
  private String value;
  private Filter sub;
  private Filter next;
}
